﻿Imports SharpNeatLib.Maths

Public Class blockProcessorClass

    Public Shared rand As FastRandom = Nothing
    Public Shared image(3) As ImageHolder
    Public Shared encoded(2) As ImageHolder
    Public startIndex As Integer = 0
    Public endIndex As Integer = 0

    Public imageWidth As Integer = 0
    Public imageHeight As Integer = 0
    Public imageStride As Integer = 0

    Public encodedWidth As Integer = 0
    Public encodedHeight As Integer = 0
    Public encodedStride As Integer = 0

    Public Shared additionalPixel(,) As Integer = New Integer(3, 2) {{1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2}}
    Public Shared twoWhite(,) As Integer = New Integer(4, 1) {{0, 1}, {0, 2}, {0, 3}, {1, 3}, {1, 2}}
    Public Shared threeWhite(,) As Integer = New Integer(9, 2) {{0, 1, 2}, {0, 1, 3}, {0, 2, 1}, {0, 2, 3}, {0, 3, 1}, {0, 3, 2}, {1, 3, 0}, {1, 3, 2}, {1, 2, 0}, {1, 2, 3}}
    Public Shared twoWhiteInverse(,) As Integer = New Integer(4, 1) {{2, 3}, {1, 3}, {1, 2}, {0, 2}, {0, 3}}

    Public Sub New(ByVal image1 As ImageHolder, ByVal image2 As ImageHolder, ByVal image3 As ImageHolder, ByVal encoded1 As ImageHolder, ByVal encoded2 As ImageHolder, ByVal startIndex As Integer, ByVal endIndex As Integer)
        image(0) = image1
        image(1) = image2
        image(2) = image3
        encoded(0) = encoded1
        encoded(1) = encoded2
        imageWidth = image1.bitmap.Width
        imageHeight = image1.bitmap.Height
        imageStride = image1.stride

        encodedWidth = encoded1.bitmap.Width
        encodedHeight = encoded1.bitmap.Height
        encodedStride = encoded1.stride

        Me.startIndex = startIndex
        Me.endIndex = endIndex

        rand = New FastRandom(Now.Millisecond)
    End Sub

    'When the hidden image pixel is BLACK:

    'The combined two cypher images (OR) have to have all four subpixels set.

    'When both source images also have a black pixel, this is easy. Both cypher images need to have three out of the four subpixels set. The only constraint is that the missing subpixel is not the same on both layers. One subpixel is randomly selected on the first layer, and one is randomly select from the other three on the second layer.

    'When the first image has a black pixel (requiring three subpixels set), and the second image has a white pixel (requiring two subpixels set), as above, first, a random single subpixel is selected on the black layer to remove. Next two subpixels are randomly selected on the second layer with the constraint that one of the selected subpixels is the same as the gap in the first layer. In this way, when the two are combined, four black subpixels are displayed.

    'The opposite happens when the first layer is white, and the second layer is black.

    'Finally, if both source pixels are white (requiring just two subpixels set), two subpixels are selected at random on the first layer, and the inverse of this selection used for the second layer.



    'When the hidden image pixel is WHITE:

    'The combined two cypher images (OR) have to have any three subpixels set.

    'When both source images have a black pixel, this is easy. Both cypher images need to have three out of the four subpixels set, and these need to be the same subpixels. Three subpixels are randomly selected and these are set on both of the cypher image layers.

    'When the first image has a black pixel (requiring three subpixels set), and the second image has a white pixel (requiring two subpixels set), as above, first, three random subpixels are selected on the first layer. Next one of these three subpixels is randomly selected for removal and this pattern is used on the second layer.

    'The opposite happens when the first layer is white, and the second layer is black.

    'Finally, if both source pixels are white (requiring two subpixels set), two are selected at random on the first layer, then one of these is duplicated on the second layer, and a second random subpixel is selected on the second layer (from the two white subpixels not selected on the first layer). Both layers have two subpixels, and when combined, there are three subpixels visbile.

    Public Sub updateRange()

        Dim layer1Pixel As Integer = 0
        Dim layer2Pixel As Integer = 0
        Dim pixel3 As Integer = 0

        Dim imageOnePixel As Integer = 0
        Dim imageTwoPixel As Integer = 0
        Dim hiddenPixel As Integer = 0

        Dim visiblePixelTotal As Integer = 0

        Dim output(2, 4) As Byte
        Dim sourcePixelAddress As Integer = ((startIndex \ imageWidth) * imageStride) + ((startIndex Mod imageWidth) * 4)
        Dim encodedPixelAddress As Integer = (((startIndex \ imageWidth) * encodedStride) + (((startIndex Mod imageWidth) * 4))) * 2

        Dim XPosition As Integer = startIndex Mod imageWidth

        For pixelIndex As Integer = startIndex To endIndex

            imageOnePixel = (image(0).ImageBytes(sourcePixelAddress) \ 255) * 255
            imageTwoPixel = (image(1).ImageBytes(sourcePixelAddress) \ 255) * 255
            hiddenPixel = (image(2).ImageBytes(sourcePixelAddress) \ 255) * 255

            visiblePixelTotal = imageOnePixel + imageTwoPixel

            output(0, 0) = 0
            output(0, 1) = 0
            output(0, 2) = 0
            output(0, 3) = 0

            output(1, 0) = 0
            output(1, 1) = 0
            output(1, 2) = 0
            output(1, 3) = 0

            If hiddenPixel = 0 Then
                If visiblePixelTotal = 0 Then 'All black pixels.
                    'When both source images also have a black pixel:
                    'Both cypher images need to have three out of the four subpixels set (black).
                    'The only constraint is that the missing subpixel is not the same on both layers.
                    'One subpixel is randomly selected on the first layer, and one is randomly select from the other three on the second layer.
                    layer1Pixel = rand.Next(0, 4)
                    layer2Pixel = rand.Next(0, 3)
                    output(0, layer1Pixel) = 255
                    output(1, additionalPixel(layer1Pixel, layer2Pixel)) = 255
                End If
                If visiblePixelTotal = 510 Then 'Both layers are white.
                    'When both source pixels are white:
                    'Two subpixels are set (black) at random on the first layer, and the inverse of this selection used for the second layer.
                    layer1Pixel = rand.Next(0, 5)
                    output(0, twoWhite(layer1Pixel, 0)) = 255
                    output(0, twoWhite(layer1Pixel, 1)) = 255
                    output(1, twoWhiteInverse(layer1Pixel, 0)) = 255
                    output(1, twoWhiteInverse(layer1Pixel, 1)) = 255
                End If
                If visiblePixelTotal = 255 Then
                    'When the first image has a black pixel (requiring three subpixels set),
                    'and the second image has a white pixel (requiring two subpixels set):
                    'a random single subpixel is selected on the black layer to remove. Next two subpixels are randomly selected
                    'on the second layer with the constraint that one of the selected subpixels is the same as the gap in the first layer.
                    'In this way, when the two are combined, four black subpixels are displayed.
                    If imageTwoPixel = 255 Then
                        layer1Pixel = rand.Next(0, 10)
                        output(1, threeWhite(layer1Pixel, 0)) = 255
                        output(1, threeWhite(layer1Pixel, 1)) = 255
                        output(0, threeWhite(layer1Pixel, 2)) = 255

                    Else
                        layer1Pixel = rand.Next(0, 10)
                        output(1, threeWhite(layer1Pixel, 2)) = 255
                        output(0, threeWhite(layer1Pixel, 0)) = 255
                        output(0, threeWhite(layer1Pixel, 1)) = 255
                    End If
                End If
            Else
                'The hidden pixel is white.
                If visiblePixelTotal = 0 Then
                    'When both source images have a black pixel, both cypher images need to have three out of the four subpixels set (black),
                    'and these need to be the same subpixels. Three subpixels are randomly selected and these are set on both of the cypher image layers.
                    layer1Pixel = rand.Next(0, 4)
                    output(0, layer1Pixel) = 255
                    output(1, layer1Pixel) = 255
                End If
                If visiblePixelTotal = 510 Then
                    'When both source pixels are white:
                    'two are selected at random on the first layer:
                    'then one of these is duplicated on the second layer, and a second random subpixel is selected on the second layer
                    '(from the two white subpixels not selected on the first layer).
                    'Both layers have two subpixels, and when combined, there are three subpixels visbile.
                    layer1Pixel = rand.Next(0, 5)
                    output(0, twoWhite(layer1Pixel, 0)) = 255
                    output(0, twoWhite(layer1Pixel, 1)) = 255
                    pixel3 = twoWhite(layer1Pixel, rand.Next(0, 2))
                    layer2Pixel = rand.Next(0, 2)
                    output(1, pixel3) = 255
                    output(1, twoWhiteInverse(layer1Pixel, layer2Pixel)) = 255
                End If
                If visiblePixelTotal = 255 Then
                    'When the first image has a black pixel, and the second image has a white pixel:
                    'Three random subpixels are selected on the first layer.
                    'Next one of these three subpixels is randomly selected for removal and this pattern is used on the second layer.
                    If imageOnePixel = 0 Then
                        layer1Pixel = rand.Next(0, 4)
                        layer2Pixel = rand.Next(0, 3)
                        output(0, layer1Pixel) = 255
                        output(1, layer1Pixel) = 255
                        output(1, additionalPixel(layer1Pixel, layer2Pixel)) = 255
                    Else
                        layer1Pixel = rand.Next(0, 4)
                        layer2Pixel = rand.Next(0, 3)
                        output(0, layer1Pixel) = 255
                        output(0, additionalPixel(layer1Pixel, layer2Pixel)) = 255
                        output(1, layer1Pixel) = 255
                    End If
                End If
            End If


            'Save to large images.
            encoded(0).ImageBytes(encodedPixelAddress) = output(0, 0)
            encoded(0).ImageBytes(encodedPixelAddress + 1) = output(0, 0)
            encoded(0).ImageBytes(encodedPixelAddress + 2) = output(0, 0)
            encoded(0).ImageBytes(encodedPixelAddress + 3) = 255 - output(0, 0)

            encoded(0).ImageBytes(encodedPixelAddress + 4) = output(0, 1)
            encoded(0).ImageBytes(encodedPixelAddress + 5) = output(0, 1)
            encoded(0).ImageBytes(encodedPixelAddress + 6) = output(0, 1)
            encoded(0).ImageBytes(encodedPixelAddress + 7) = 255 - output(0, 1)

            encoded(0).ImageBytes(encodedPixelAddress + encodedStride) = output(0, 2)
            encoded(0).ImageBytes(encodedPixelAddress + encodedStride + 1) = output(0, 2)
            encoded(0).ImageBytes(encodedPixelAddress + encodedStride + 2) = output(0, 2)
            encoded(0).ImageBytes(encodedPixelAddress + encodedStride + 3) = 255 - output(0, 2)

            encoded(0).ImageBytes(encodedPixelAddress + encodedStride + 4) = output(0, 3)
            encoded(0).ImageBytes(encodedPixelAddress + encodedStride + 5) = output(0, 3)
            encoded(0).ImageBytes(encodedPixelAddress + encodedStride + 6) = output(0, 3)
            encoded(0).ImageBytes(encodedPixelAddress + encodedStride + 7) = 255 - output(0, 3)

            encoded(1).ImageBytes(encodedPixelAddress) = output(1, 0)
            encoded(1).ImageBytes(encodedPixelAddress + 1) = output(1, 0)
            encoded(1).ImageBytes(encodedPixelAddress + 2) = output(1, 0)
            encoded(1).ImageBytes(encodedPixelAddress + 3) = 255 - output(1, 0)

            encoded(1).ImageBytes(encodedPixelAddress + 4) = output(1, 1)
            encoded(1).ImageBytes(encodedPixelAddress + 5) = output(1, 1)
            encoded(1).ImageBytes(encodedPixelAddress + 6) = output(1, 1)
            encoded(1).ImageBytes(encodedPixelAddress + 7) = 255 - output(1, 1)

            encoded(1).ImageBytes(encodedPixelAddress + encodedStride) = output(1, 2)
            encoded(1).ImageBytes(encodedPixelAddress + encodedStride + 1) = output(1, 2)
            encoded(1).ImageBytes(encodedPixelAddress + encodedStride + 2) = output(1, 2)
            encoded(1).ImageBytes(encodedPixelAddress + encodedStride + 3) = 255 - output(1, 2)

            encoded(1).ImageBytes(encodedPixelAddress + encodedStride + 4) = output(1, 3)
            encoded(1).ImageBytes(encodedPixelAddress + encodedStride + 5) = output(1, 3)
            encoded(1).ImageBytes(encodedPixelAddress + encodedStride + 6) = output(1, 3)
            encoded(1).ImageBytes(encodedPixelAddress + encodedStride + 7) = 255 - output(1, 3)

            XPosition += 1
            If XPosition < imageWidth Then
                sourcePixelAddress += 4
                encodedPixelAddress += 8
            Else
                XPosition = 0
                sourcePixelAddress += (4 + ((imageStride - (imageWidth * 4))))
                encodedPixelAddress += (8 + (encodedStride + (encodedStride - (encodedWidth * 4))))
            End If
        Next
    End Sub

End Class
